package panda.query.condition;

import panda.query.scan.Scanner;
import panda.query.struct.Attribute;
import panda.query.struct.Constant;
import panda.query.struct.FloatConstant;
import panda.query.struct.IntConstant;
import panda.record.Schema;
import panda.transaction.Transaction;

public class OpExpression implements ValueExpression {
	ValueExpression l, r;
	int op;
	
	public OpExpression(ValueExpression l, int op, ValueExpression r) {
		this.l = l;
		this.r = r;
		this.op = op;
	}
	
	public Constant evaluate(Scanner s, Transaction tx) {
		Constant lc = l.evaluate(s, tx);
		Constant rc = r.evaluate(s, tx);
		
		if (lc instanceof IntConstant && rc instanceof IntConstant) {
			switch (op) {
			case ADD : 
				return new IntConstant((Integer)lc.getContentValue() + (Integer)rc.getContentValue());
			case SUB : 
				return new IntConstant((Integer)lc.getContentValue() - (Integer)rc.getContentValue());
			case MUL : 
				return new IntConstant((Integer)lc.getContentValue() * (Integer)rc.getContentValue());
			case DIV : 
				return new IntConstant((Integer)lc.getContentValue() / (Integer)rc.getContentValue());
			case MOD : 
				return new IntConstant((Integer)lc.getContentValue() % (Integer)rc.getContentValue());
			}
		}
		
		if (lc instanceof FloatConstant || rc instanceof FloatConstant) {
			switch (op) {
			case ADD : 
				return new FloatConstant(lc.getFloatValue() + rc.getFloatValue());
			case SUB : 
				return new FloatConstant(lc.getFloatValue() - rc.getFloatValue());
			case MUL : 
				return new FloatConstant(lc.getFloatValue() * rc.getFloatValue());
			case DIV : 
				return new FloatConstant(lc.getFloatValue() / rc.getFloatValue());
//			case MOD : 
//				return new FloatConstant((Float)lc.getContentValue() % (Float)rc.getContentValue());
			}
		}
		
		return null;
	}

	public boolean dominates(Attribute attr) {
		return l.dominates(attr) != r.dominates(attr);
	}

	public boolean isConstant() {
		return l.isConstant() && r.isConstant();
	}
	
	public Constant asConstant() {
		if (isConstant())
			return evaluate(null, null);
		else
			return null;
	}
	
	public boolean appliesTo(Schema sch) {
		return l.appliesTo(sch) && r.appliesTo(sch);
	}
	
	public static final int ADD = 0;
	public static final int SUB = 1;
	public static final int MUL = 2;
	public static final int DIV = 3;
	public static final int MOD = 4;


}
